﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Common;
using CSC440TeamOne.CSC440BusinessService.Interface.Services;
using Microsoft.Practices.CompositeWeb;
using Microsoft.Practices.Unity.Utility;

namespace CSC440TeamOne.CSC440BusinessService.Services
{
    /// <summary>
    /// Name - ProductionBusinessService.cs
    /// Description - 
    ///     Ties services and Common Objects together to service requests from the user
    ///     Production version of Business Service
    /// Programmer - Matthew Mitchell
    /// Date coded - 11/27/2011
    /// Arguments - None
    /// Variables - None
    /// Files accessed by this code artifact - None
    /// Files changed by this code artifact - None
    /// I/O - None
    /// Error Handling - None
    /// Modifications -
    ///     1.0 - Initial coding
    /// Known Faults -
    ///     1.0 - None known
    /// </summary>
    public class ProductionBusinessService : IBusinessService
    {
        private ISecurityService _SecurityService;
        private IDataService _DataService;

        private List<Question> questionList;

        /// <summary>
        /// Initializes a new instance of the <see cref="ProductionBusinessService"/> class.
        /// </summary>
        /// <param name="securityService">The security service.</param>
        /// <param name="dataService">The data service.</param>
        public ProductionBusinessService([ServiceDependency]ISecurityService securityService, [ServiceDependency]IDataService dataService)
        {
            _SecurityService = securityService;

            _DataService = dataService;

            questionList = new List<Question>();

            this.questionList = _DataService.populateQuestionList(); // Populate during instantiation so the values carry between pages (allows editing)
        }

        public void AddUser(User user)
        {
            throw new NotImplementedException();
        }

        public User FindUserById(string id)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Returns the full questionaire question list to the controller requesting it
        /// </summary>
        /// <returns>List continaing all questionaire questions</returns>
        public List<Question> LoadAllQuestions()
        {
            return this.questionList;
        }

        /// <summary>
        /// Saves specific questionaire answer to list
        /// </summary>
        /// <param name="questionID">Question ID</param>
        /// <param name="answer">Text of the answer chosen</param>
        public void SaveQuestionaireAnswer(int questionID, string answer)
        {
            foreach (Question q in questionList)
            {
                if (q.QuestionID == questionID)
                {
                    // Checkboxes can have multiple answers, so the answer must be stored in the child control
                    if (q.AnswerControlType == Question.Types.CheckBox)
                    {
                        foreach (Question a in q.ChildItems)
                        {
                            if (a.QuestionText == answer)
                            {
                                a.AnswerText = answer;
                                a.Answered = true;
                            }
                        }
                    }
                    else
                    {
                        // All other question types save in the question header
                        q.AnswerText = answer;
                    }

                    q.Answered = true;

                    break;
                }
            }
        }


        /// <summary>
        /// Loads the daily entry view for current user.
        /// </summary>
        /// <returns></returns>
        public DailyEntryViewModel LoadDailyEntryViewForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadDailyEntryViewForCurrentUser");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var dailyTrackableHealthParameters = _DataService.LoadDailyTrackableHealthParametersForUser(user);

                Guard.ArgumentNotNull(dailyTrackableHealthParameters, "dailyTrackableHealthParameters");

                Debug.WriteLine("end DummyService.LoadDailyEntryViewForCurrentUser");

                return new DailyEntryViewModel()
                {
                    HealthParameters = dailyTrackableHealthParameters
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Loads the health progress for current user.
        /// </summary>
        /// <returns></returns>
        public MyProgressViewModel LoadHealthProgressForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadHealthProgressForCurrentUser");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var trackableHealthParameters = _DataService.LoadTrackableHealthParameterProgressForUser(user);

                Guard.ArgumentNotNull(trackableHealthParameters, "trackableHealthParameters");

                bool hasMaxTolerance = true, hasMinTolerance = true;//TODO: why did i need these?

                Debug.WriteLine("end DummyService.LoadHealthProgressForCurrentUser");

                return new MyProgressViewModel()
                {
                    TrackableHealthParameters = trackableHealthParameters,
                    HasMaxTolerance = hasMaxTolerance,
                    HasMinTolerance = hasMinTolerance
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Loads the user health goals for current user.
        /// </summary>
        /// <returns></returns>
        public MyHealthGoalConfigViewModel LoadUserHealthGoalsForCurrentUser()
        {
            Debug.WriteLine("start DummyService.LoadUserHealthGoalsForCurrentUser");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var healthGoals = _DataService.FindHeathGoalsForUser(user);

                Guard.ArgumentNotNull(healthGoals, "healthGoals");

                Debug.WriteLine("end DummyService.LoadUserHealthGoalsForCurrentUser");

                return new MyHealthGoalConfigViewModel()
                {
                    HealthGoals = healthGoals
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Saves the health config.
        /// </summary>
        /// <param name="model">The model.</param>
        public void SaveHealthConfig(MyHealthGoalConfigViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveHealthConfig");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var healthGoals = model.ChangedHealthGoals();

                Guard.ArgumentNotNull(healthGoals, "healthGoals");

                if (healthGoals.Any())
                {
                    foreach (var healthGoal in healthGoals)
                    {
                        _DataService.SaveUserHealthGoal(user, healthGoal);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveHealthConfig");
        }

        public SubmitRecipeModel getNewRecipeViewModel()
        {
            throw new NotImplementedException();
        }

        public void parse(SubmitRecipeModel model)
        {
            throw new NotImplementedException();
        }

        public ProcessRegistrationModel LoadProcessRegistrationModel()
        {
            throw new NotImplementedException();
        }

        public MyRecipeViewModel LoadMyRecipeViewModelForCurrentUser()
        {
            throw new NotImplementedException();
        }

        public void saveViewRecipeModel(MyRecipeViewModel model)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Loads the tolerance config items.
        /// </summary>
        /// <returns></returns>
        public ToleranceConfigListViewModel LoadToleranceConfigItems()
        {
            Debug.WriteLine("start DummyService.LoadToleranceConfigItems");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var userRole = user.UserRole;

                Microsoft.Practices.CompositeWeb.Utility.Guard.EnumValueIsDefined(typeof(UserRole), userRole, "userRole");

                IEnumerable<HealthParameter> healthParameters = new HealthParameter[] { };

                Guard.ArgumentNotNull(healthParameters, "healthParameters");

                if (userRole == UserRole.administrator || userRole == UserRole.developer)
                {
                    healthParameters = _DataService.LoadAllHealthParameters();

                    Guard.ArgumentNotNull(healthParameters, "healthParameters");
                }

                Debug.WriteLine("end DummyService.LoadToleranceConfigItems");

                return new ToleranceConfigListViewModel()
                {
                    HealthParameters = healthParameters
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Loads the health parameter by ID.
        /// </summary>
        /// <param name="healthParameterID">The health parameter ID.</param>
        /// <returns></returns>
        public ToleranceConfigDetailsViewModel LoadHealthParameterByID(int healthParameterID)
        {
            Guard.ArgumentNotNull(healthParameterID, "healthParameterID");

            Debug.WriteLine("start DummyService.LoadHealthParameterByID");

            try
            {
                var user = _SecurityService.LoadCurrentUser();

                Guard.ArgumentNotNull(user, "user");

                var userRole = user.UserRole;

                Microsoft.Practices.CompositeWeb.Utility.Guard.EnumValueIsDefined(typeof(UserRole), userRole, "userRole");

                var healthParameter = HealthParameter.Empty;

                var userCanEditHealthParameter = false;

                if (userRole == UserRole.administrator || userRole == UserRole.developer)
                {
                    healthParameter = _DataService.FindHealthParameterById(healthParameterID);

                    userCanEditHealthParameter = true;

                    Guard.ArgumentNotNull(healthParameter, "healthParameter");
                }

                Debug.WriteLine("end DummyService.LoadHealthParameterByID");

                return new ToleranceConfigDetailsViewModel()
                {
                    HealthParameter = healthParameter,
                    UserCanEditHealthParameter = userCanEditHealthParameter
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Saves the health parameter config.
        /// </summary>
        /// <param name="model">The model.</param>
        public void SaveHealthParameterConfig(ToleranceConfigDetailsViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveHealthParameterConfig");

            try
            {
                var healthParameter = model.HealthParameter;

                Guard.ArgumentNotNull(healthParameter, "healthParameter");

                _DataService.Update(healthParameter);
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveHealthParameterConfig");
        }

        /// <summary>
        /// Saves the daily entry view model.
        /// </summary>
        /// <param name="model">The model.</param>
        public void SaveDailyEntryViewModel(DailyEntryViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            Debug.WriteLine("start DummyService.SaveDailyEntryViewModel");

            try
            {
                IEnumerable<TrackableHealthParameter> dailyHealthParameters = model.ChangedHealthParameters();

                Guard.ArgumentNotNull(dailyHealthParameters, "dailyHealthParameters");

                if (dailyHealthParameters.Any())
                {
                    var user = _SecurityService.LoadCurrentUser();

                    Guard.ArgumentNotNull(user, "user");

                    foreach (var dailyHealthParameter in dailyHealthParameters)
                    {
                        var newId = _DataService.InsertDailyHealthParameterForUser(dailyHealthParameter, user);

                        Guard.ArgumentNotNull(newId, "newId");

                        Debug.Assert(newId > 0);

                        dailyHealthParameter.ID = newId;
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }

            Debug.WriteLine("end DummyService.SaveDailyEntryViewModel");
        }

        public void LoadRecipe(MyRecipeViewModel model)
        {
            throw new NotImplementedException();
        }

        public void LoadRecipeByValue(MyRecipeViewModel model)
        {
            throw new NotImplementedException();
        }

        public void LoadVerifyRecipeModel(VerifyRecipeModel m)
        {
            //check for null argument, throws exception if null
            Guard.ArgumentNotNull(m, "model");
            int recipeID = m.recipeID;
            Recipe recipe = _DataService.FindRecipeByID(recipeID);
            m.Recipe = recipe;
        }

        public MyFoodTrackerViewModel LoadMyFoodTrackerViewModelForCurrentUser()
        {
            throw new NotImplementedException();
        }

        public void LoadRecipe(MyFoodTrackerViewModel model)
        {
            throw new NotImplementedException();
        }

        public void LoadRecipeByValue(MyFoodTrackerViewModel model)
        {
            throw new NotImplementedException();
        }

        public void LoadPrintableRecipe(MyRecipeViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");
            int recipeID = model.selectedRecipeID;
            List<Recipe> recipe = _DataService.LoadPrintRecipe(recipeID);
            model.searchResults = recipe;
        }

        public void LoadPrintableRecipe2(MyRecipeViewModel model)
        {
            Guard.ArgumentNotNull(model, "model");
            int recipeID = model.selectedRecipeID;
            Recipe recipe = _DataService.LoadPrintRecipe2(recipeID);
            model.selectedRecipe = recipe;
        }

        public void LoadMyHealthSnapshotModel(MyHealthSnapshotModel model)
        {
            User u = _SecurityService.LoadCurrentUser();
            List<TrackableHealthParameter> healthParameters = _DataService.LoadCurrentTrackableHealthParametersForUser(u);

            model.systolic = healthParameters[0];
            model.diastolic = healthParameters[1];
            model.waist = healthParameters[2];
            model.bmi = healthParameters[3];
            model.cholesterol = healthParameters[4];
            model.glucose = healthParameters[5];
            model.physicalActivity = healthParameters[6];
            model.restingHeart = healthParameters[7];
        }

        /// <summary>
        /// Sets the help text on a particular question in the questionaire list
        /// </summary>
        /// <param name="questionID">Question ID of the questionaire question</param>
        /// <param name="helpText">HelpText object containing popup values</param>
        public void saveHelpText(int questionID, HelpText helpText)
        {
            // Loop through the questions, when the ID matches, set the help text
            foreach (Question q in this.questionList)
            {
                if (q.QuestionID == questionID)
                {
                    q.HelpText = helpText;
                    break;
                }
            }
        }

        /// <summary>
        /// Gets the index of the user manual model by current.
        /// </summary>
        /// <param name="sectionId">The section id.</param>
        /// <returns></returns>
        public UserManualModel GetUserManualModelByCurrentIndex(int sectionId)
        {
            try
            {
                Debug.WriteLine("start IBusinessService.GetUserManualModelByCurrentIndex");

                var allUserManualSections = _DataService.LoadAllUserManualSections();

                var userManualSectionCollection = new UserManualSectionCollection(allUserManualSections);

                var currentUserManualSection = userManualSectionCollection.Root;

                if (sectionId > 0)
                {
                    currentUserManualSection = userManualSectionCollection.FindUserManualSectionById(sectionId);

                    var userManualContents = _DataService.FindForUserManualSection(currentUserManualSection);

                    if (userManualContents.Any())
                    {
                        foreach (var userManualContent in userManualContents)
                        {
                            currentUserManualSection.AddContent(userManualContent);
                        }
                    }
                }

                Debug.WriteLine("end IBusinessService.GetUserManualModelByCurrentIndex");

                return new UserManualModel()
                {
                    CurrentUserManualSection = currentUserManualSection,
                    UserManualSectionMap = userManualSectionCollection
                };
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Adds the content of the user manual.
        /// </summary>
        /// <param name="model">The model.</param>
        public void AddUserManualContent(UserManualModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            try
            {
                Debug.WriteLine("start IBusinessService.AddUserManualContent");

                var currentUserManualContent = model.CurrentUserManualSection;

                currentUserManualContent.AddNewContent();

                Debug.WriteLine("end IBusinessService.AddUserManualContent");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Adds the user manual section.
        /// </summary>
        /// <param name="model">The model.</param>
        public void AddUserManualSection(UserManualModel model)
        {
            try
            {
                Guard.ArgumentNotNull(model, "model");

                Debug.WriteLine("start IBusinessService.AddUserManualSection");

                var userManualSectionMap = model.UserManualSectionMap;

                var currentUserManualSection = model.CurrentUserManualSection;

                var newUserManualSection = userManualSectionMap.AddNewUserManualSection(currentUserManualSection.Id);

                newUserManualSection.Title = "New Section";

                newUserManualSection.AddNewContent();

                model.CurrentUserManualSection = newUserManualSection;

                Debug.WriteLine("end IBusinessService.AddUserManualSection");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }

        /// <summary>
        /// Saves the user manual model.
        /// </summary>
        /// <param name="model">The model.</param>
        public void SaveUserManualModel(UserManualModel model)
        {
            Guard.ArgumentNotNull(model, "model");

            var userManualSection = model.CurrentUserManualSection;

            Guard.ArgumentNotNull(userManualSection, "currentUserManualSection");

            try
            {
                Debug.WriteLine("start IBusinessService.SaveUserManualModel");

                if (userManualSection.Id < 1)
                {
                    userManualSection.Id = _DataService.InsertUserManualSection(userManualSection);

                    foreach (var userManualContent in userManualSection.Content)
                    {
                        userManualContent.UserManualSectionId = userManualSection.Id;
                    }
                }
                else
                {
                    _DataService.UpdateUserManualSection(userManualSection);
                }

                foreach (var userManualContent in userManualSection.Content)
                {
                    if (userManualContent.Id < 1)
                    {
                        userManualContent.Id = _DataService.InsertUserManualContent(userManualContent);
                    }
                    else
                    {
                        _DataService.UpdateUserManualContent(userManualContent);
                    }
                }

                Debug.WriteLine("end IBusinessService.SaveUserManualModel");
            }
            catch (Exception ex)
            {
                Trace.TraceError(ex.ToString());

                throw;
            }
        }


        public void FindRecipeByIDforModel(VerifyRecipeModel model)
        {
            Guard.ArgumentNotNull(model, "model");  
            var recipeID = model.recipeID;
            var recipe = _DataService.FindRecipeByID(recipeID);
            model.Recipe = recipe;
        }


        public void LoadSubmittedRecipesModel(SubmittedRecipesModel model)
        {
            Guard.ArgumentNotNull(model, "model");
            model.recipes = _DataService.LoadListOfSubmittedRecipes();
        }


        public User LoadCurrentUser()
        {
            return _SecurityService.LoadCurrentUser();
        }

        public SubmittedRecipesModel LoadSubmittedRecipesModel()
        {
            throw new NotImplementedException();
        }

        public VerifyRecipeModel LoadVerifyRecipeModel(int id)
        {
            throw new NotImplementedException();
        }

        public MyHealthSnapshotModel LoadMyHealthSnapshotModel()
        {
            throw new NotImplementedException();
        }
    }
}
